package com.tianletan.pool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

// 数据源 连接池
public class MyDataSource extends MyAbstractDataSource{

    private final List<ConnectionProxy> idleConnections = new ArrayList<>();

    private final List<ConnectionProxy> activeConnections = new ArrayList<>();

    private int poolMaxActiveConnections = 2; //最大正使用连接数

    private int poolMaxIdleConnections = 1; //最大空闲连接数

    private int poolTimeToWait = 30000; //从连接池中获取一个连接最多等待多少ms

    private final Object monitor = new Object(); //用于同步的监视器对象

    // 覆盖父类的方法，返回一个动态代理连接（封装）
    @Override
    public Connection getConnection() throws SQLException {

        ConnectionProxy connectionProxy = getConnectionProxy(super.getUsername(), super.getPassword());

        return connectionProxy.getProxyConnection();
    }

    public ConnectionProxy getConnectionProxy(String username, String password) throws SQLException {
        ConnectionProxy connectionProxy = null;

        // 最初没有连接
        while(connectionProxy == null){
            // 做一个同步线程？启动一个新线程？
            synchronized (monitor){
                System.out.println(Thread.currentThread().getName() + " enters synchronized block");
                if (!idleConnections.isEmpty()){
                    connectionProxy = idleConnections.remove(0);
                } else {
                    if (activeConnections.size() < poolMaxActiveConnections){
                        connectionProxy = new ConnectionProxy(super.getConnection(username, password), this);

                        System.out.println(Thread.currentThread().getName() + " gets " + connectionProxy);
                    } else {
                        // 否则需要等待poolTimeToWait = 30000ms
                        try {
                            System.out.println(Thread.currentThread().getName() + " is waiting...");
                            monitor.wait(poolTimeToWait);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                System.out.println(Thread.currentThread().getName() + " exits synchronized block");
            }
        }

        if (connectionProxy != null) {
            activeConnections.add(connectionProxy);
        }
        return connectionProxy;
    }

    // 将空闲连接放入 连接池
    public void closeConnection(ConnectionProxy connectionProxy){
        synchronized (monitor){
            activeConnections.remove(connectionProxy);

            if(idleConnections.size() < poolMaxIdleConnections){
                idleConnections.add(connectionProxy);
            }

            // 通知等待获取 空闲连接的线程
            monitor.notifyAll();
        }
    }
}
